package com.example.common.grpc;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * gRPC连接配置类
 * 提供优化的连接参数，避免too_many_pings等问题
 * 
 * @author: Allen
 * @create: 2025/1/27 12:00
 * @description: gRPC连接配置类
 **/
@Slf4j
@Component
public class GrpcChannelConfig {
    
    /**
     * 创建优化的gRPC Channel
     * 
     * @param host 主机地址
     * @param port 端口
     * @return ManagedChannel
     */
    public ManagedChannel createOptimizedChannel(String host, int port) {
        return ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                // Keepalive配置 - 避免too_many_pings问题
                .keepAliveTime(60, TimeUnit.SECONDS)      // 60秒发送一次keepalive ping
                .keepAliveTimeout(10, TimeUnit.SECONDS)   // keepalive ping超时时间
                .keepAliveWithoutCalls(false)             // 关闭无调用时的keepalive
                // 消息大小配置
                .maxInboundMessageSize(1024 * 1024)       // 1MB最大消息大小
                .maxInboundMetadataSize(1024 * 1024)      // 1MB最大元数据大小
                // 连接配置
                .enableFullStreamDecompression()          // 启用完整流解压缩
                .build();
    }
    
    /**
     * 创建高性能gRPC Channel（适用于高频调用场景）
     * 
     * @param host 主机地址
     * @param port 端口
     * @return ManagedChannel
     */
    public ManagedChannel createHighPerformanceChannel(String host, int port) {
        return ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                // 高频场景的keepalive配置
                .keepAliveTime(30, TimeUnit.SECONDS)      // 30秒发送一次keepalive ping
                .keepAliveTimeout(5, TimeUnit.SECONDS)    // keepalive ping超时时间
                .keepAliveWithoutCalls(true)              // 允许无调用时的keepalive
                // 消息大小配置
                .maxInboundMessageSize(2 * 1024 * 1024)   // 2MB最大消息大小
                .maxInboundMetadataSize(2 * 1024 * 1024)  // 2MB最大元数据大小
                // 连接配置
                .enableFullStreamDecompression()          // 启用完整流解压缩
                .build();
    }
    
    /**
     * 创建低延迟gRPC Channel（适用于实时通信场景）
     * 
     * @param host 主机地址
     * @param port 端口
     * @return ManagedChannel
     */
    public ManagedChannel createLowLatencyChannel(String host, int port) {
        return ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                // 低延迟场景的keepalive配置
                .keepAliveTime(15, TimeUnit.SECONDS)      // 15秒发送一次keepalive ping
                .keepAliveTimeout(3, TimeUnit.SECONDS)    // keepalive ping超时时间
                .keepAliveWithoutCalls(true)              // 允许无调用时的keepalive
                // 消息大小配置
                .maxInboundMessageSize(512 * 1024)        // 512KB最大消息大小
                .maxInboundMetadataSize(512 * 1024)       // 512KB最大元数据大小
                // 连接配置
                .enableFullStreamDecompression()          // 启用完整流解压缩
                .build();
    }
    
    /**
     * 创建保守配置的gRPC Channel（适用于稳定性和可靠性优先的场景）
     * 
     * @param host 主机地址
     * @param port 端口
     * @return ManagedChannel
     */
    public ManagedChannel createConservativeChannel(String host, int port) {
        return ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                // 保守的keepalive配置
                .keepAliveTime(15, TimeUnit.SECONDS)     // 120秒发送一次keepalive ping
                .keepAliveTimeout(15, TimeUnit.SECONDS)   // keepalive ping超时时间
                // 消息大小配置
                .maxInboundMessageSize(5 * 1024 * 1024)        // 512KB最大消息大小
                // 连接配置
                .build();
    }
    
    /**
     * 根据服务类型选择合适的Channel配置
     * 
     * @param host 主机地址
     * @param port 端口
     * @param serviceType 服务类型
     * @return ManagedChannel
     */
    public ManagedChannel createChannelByServiceType(String host, int port, String serviceType) {
        switch (serviceType.toLowerCase()) {
            case "gate":
            case "gate-service":
                // Gate服务通常需要低延迟
                return createLowLatencyChannel(host, port);
                
            case "lobby":
            case "lobby-service":
                // Lobby服务需要平衡性能和稳定性
                return createOptimizedChannel(host, port);
                
            case "game":
            case "game-service":
                // Game服务需要高性能
                return createHighPerformanceChannel(host, port);
            default:
                // 默认使用保守配置
                return createConservativeChannel(host, port);
        }
    }
    
    /**
     * 检查Channel配置是否合理
     * 
     * @param channel ManagedChannel
     * @return 是否配置合理
     */
    public boolean isChannelConfigReasonable(ManagedChannel channel) {
        try {
            // 检查Channel状态
            io.grpc.ConnectivityState state = channel.getState(true);
            
            // 检查是否在合理时间内能够建立连接
            boolean isReady = channel.getState(true) == io.grpc.ConnectivityState.READY;
            
            if (isReady) {
                log.debug("Channel配置合理，状态: {}", state);
                return true;
            } else {
                log.warn("Channel配置可能存在问题，状态: {}", state);
                return false;
            }
            
        } catch (Exception e) {
            log.error("检查Channel配置时发生错误", e);
            return false;
        }
    }
    
    /**
     * 获取Channel配置建议
     * 
     * @param serviceType 服务类型
     * @return 配置建议
     */
    public String getChannelConfigAdvice(String serviceType) {
        switch (serviceType.toLowerCase()) {
            case "gate":
            case "gate-service":
                return "建议使用低延迟配置：keepAliveTime=15s, keepAliveTimeout=3s";
                
            case "lobby":
            case "lobby-service":
                return "建议使用平衡配置：keepAliveTime=60s, keepAliveTimeout=10s";
                
            case "game":
            case "game-service":
                return "建议使用高性能配置：keepAliveTime=30s, keepAliveTimeout=5s";
                
            default:
                return "建议使用保守配置：keepAliveTime=120s, keepAliveTimeout=20s";
        }
    }
} 